package services

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"time"

	"blockchain-api/internal/models"
	"github.com/btcsuite/btcd/btcec/v2"
	"gorm.io/gorm"
)

// WalletService 钱包服务
type WalletService struct {
	db *gorm.DB
}

// NewWalletService 创建钱包服务
func NewWalletService(db *gorm.DB) *WalletService {
	return &WalletService{db: db}
}

// CreateWallet 创建钱包
func (s *WalletService) CreateWallet(name string) (*models.Wallet, error) {
	// 检查钱包名称是否已存在
	var existingWallet models.Wallet
	if err := s.db.Where("name = ?", name).First(&existingWallet).Error; err == nil {
		return nil, fmt.Errorf("wallet with name '%s' already exists", name)
	}

	// 生成私钥
	privateKey, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader)
	if err != nil {
		return nil, fmt.Errorf("failed to generate private key: %v", err)
	}

	// 获取公钥
	publicKey := &privateKey.PublicKey

	// 生成地址
	address, err := s.generateAddress(publicKey)
	if err != nil {
		return nil, fmt.Errorf("failed to generate address: %v", err)
	}

	// 检查地址是否已存在
	var existingAddress models.Wallet
	if err := s.db.Where("address = ?", address).First(&existingAddress).Error; err == nil {
		return nil, fmt.Errorf("wallet with address '%s' already exists", address)
	}

	// 创建钱包记录
	wallet := &models.Wallet{
		Name:      name,
		Address:   address,
		PublicKey: s.getPublicKeyHex(publicKey),
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	// 保存到数据库
	if err := s.db.Create(wallet).Error; err != nil {
		return nil, fmt.Errorf("failed to create wallet: %v", err)
	}

	return wallet, nil
}

// GetWallet 获取钱包
func (s *WalletService) GetWallet(name string) (*models.Wallet, error) {
	var wallet models.Wallet
	if err := s.db.Where("name = ?", name).First(&wallet).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("wallet not found")
		}
		return nil, err
	}
	return &wallet, nil
}

// GetWalletByAddress 根据地址获取钱包
func (s *WalletService) GetWalletByAddress(address string) (*models.Wallet, error) {
	var wallet models.Wallet
	if err := s.db.Where("address = ?", address).First(&wallet).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("wallet not found")
		}
		return nil, err
	}
	return &wallet, nil
}

// ListWallets 列出所有钱包
func (s *WalletService) ListWallets(limit, offset int) ([]models.Wallet, error) {
	var wallets []models.Wallet
	query := s.db.Model(&models.Wallet{})
	
	if limit > 0 {
		query = query.Limit(limit)
	}
	if offset > 0 {
		query = query.Offset(offset)
	}
	
	if err := query.Find(&wallets).Error; err != nil {
		return nil, err
	}
	return wallets, nil
}

// DeleteWallet 删除钱包
func (s *WalletService) DeleteWallet(name string) error {
	result := s.db.Where("name = ?", name).Delete(&models.Wallet{})
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("wallet not found")
	}
	return nil
}

// GetWalletCount 获取钱包总数
func (s *WalletService) GetWalletCount() (int64, error) {
	var count int64
	if err := s.db.Model(&models.Wallet{}).Count(&count).Error; err != nil {
		return 0, err
	}
	return count, nil
}

// generateAddress 生成地址
func (s *WalletService) generateAddress(publicKey *ecdsa.PublicKey) (string, error) {
	// 将公钥转换为未压缩格式
	pubKeyBytes := elliptic.Marshal(publicKey.Curve, publicKey.X, publicKey.Y)
	
	// 计算SHA256哈希
	hash := sha256.Sum256(pubKeyBytes)
	
	// 取前20字节作为地址
	address := hex.EncodeToString(hash[:20])
	
	return "0x" + address, nil
}

// getPublicKeyHex 获取公钥十六进制字符串
func (s *WalletService) getPublicKeyHex(publicKey *ecdsa.PublicKey) string {
	pubKeyBytes := elliptic.Marshal(publicKey.Curve, publicKey.X, publicKey.Y)
	return hex.EncodeToString(pubKeyBytes)
}

// GetPrivateKey 获取私钥（仅用于演示，实际应用中应该安全存储）
func (s *WalletService) GetPrivateKey(name string) (string, error) {
	// 注意：在实际应用中，私钥应该加密存储或使用硬件安全模块
	// 这里仅用于演示目的
	return "", fmt.Errorf("private key access not implemented for security reasons")
}

// ValidateAddress 验证地址格式
func (s *WalletService) ValidateAddress(address string) bool {
	// 移除0x前缀
	if len(address) > 2 && address[:2] == "0x" {
		address = address[2:]
	}
	
	// 检查长度（40个十六进制字符 = 20字节）
	if len(address) != 40 {
		return false
	}
	
	// 检查是否都是十六进制字符
	for _, char := range address {
		if !((char >= '0' && char <= '9') || 
			 (char >= 'a' && char <= 'f') || 
			 (char >= 'A' && char <= 'F')) {
			return false
		}
	}
	
	return true
}
